module klang.编译.输出.输出_;
import 全局;
import ··枚举值_ = klang.编译.类型.枚举值.枚举值_;
import ··类型_ = klang.编译.类型.类型_;
import ··输出工具_ = klang.编译.输出工具.输出工具_;
import klang.编译.语法节点.节点_: 源文件_, 节点_;
import klang.编译.核心.核心_: 过滤, 创建数组;
import klang.编译.系统.系统_: sys;
import klang.编译.类型.类型_: 输出结果_, 写文件回调_, 输出解析器_, 定制转换组_, 输出转换组_, 转换工厂_, 前端接口_, 程序主机接口_, TransformationResult, 打印选项_, 打印助手_, 新行种类_, 打印机_, SourceMapGenerator;
import klang.编译.输出工具.输出工具_: 创建文本写;
import klang.编译.转换.转换_: transformNodes;
import klang.编译.诊断.诊断_: 诊断_;
import klang.编译.源映射生成器.源映射_: createSourceMapGenerator;
import klang.编译.路径.路径_: 正规化反斜杠, 获取基础文件名称, 正规化路径, 获取目录路径;
import klang.编译.注册.注册_: 获取注册的前端;
alias 输出动作类型_(T) = T delegate(源文件_[], 输出转换组_, 输出结果_);
T forEachEmittedFile(T)(程序主机接口_ host, 输出动作类型_!(T) 回调, 源文件_[] 源文件组, 输出转换组_ 输出转换组, 输出结果_ 输出结果) {
    源文件_[][] 准备输出源文件 = host.准备输出源文件(源文件组);
    foreach (源文件_[] sous; 准备输出源文件) {
        T 结果 = 回调(sous, 输出转换组, 输出结果);
        if (结果 !is ··null!(T)) {
            return 结果;
        }
    }
    return ··null!(T);
}
输出结果_ emitFiles(输出解析器_ resolver, 写文件回调_ 写文件 = ··null!(写文件回调_), 源文件_ targetSourceFile = ··null!(源文件_), 输出转换组_ 输出转换组 = ··null!(输出转换组_)) {
    bool delegate(源文件_[], 输出转换组_, 输出结果_) 输出一组文件;
    void delegate(源文件_[], 转换工厂_!(节点_)[], 输出结果_) 输出多个文件为一个文件;
    void delegate(源文件_[], 转换工厂_!(节点_)[], 输出结果_) 如果需要为多个文件生成一个声明文件;
    void delegate(源文件_, 打印机_, SourceMapGenerator) 打印输出文件;
    输出结果_ 结果;
    程序主机接口_ host;
    源文件_[] 源文件组;
    ··输出工具_.EmitTextWriter 写出;
    bool 输出一组文件·func(源文件_[] 文件组, 输出转换组_ 输出转换组, 输出结果_ 输出结果) {
        如果需要为多个文件生成一个声明文件(文件组, 输出转换组.声明转换组, 输出结果);
        输出多个文件为一个文件(文件组, 输出转换组.源码转换组, 输出结果);
        return false;
    }
    输出一组文件 = &输出一组文件·func;
    void 输出多个文件为一个文件·func(源文件_[] 文件组, 转换工厂_!(节点_)[] 源码转换组, 输出结果_ 输出结果) {
        TransformationResult 转换结果;
        转换结果 = transformNodes(resolver, (cast(节点_[])(文件组)), 源码转换组);
        if ((转换结果 !is ··null!(TransformationResult)) && (转换结果.transformed !is ··null!(节点_[])) && 转换结果.transformed.length > 0) {
            foreach (节点_ s; 转换结果.transformed) {
                if (!host.获取前端().是应输出的文件((cast(源文件_)(s)))) {
                    continue;
                }
                dstring mapFileName = 获取基础文件名称(正规化反斜杠((cast(源文件_)(s)).输出文件名));
                SourceMapGenerator sourceMapGen = createSourceMapGenerator(host, mapFileName, ""d, 获取目录路径(正规化路径((cast(源文件_)(s)).输出文件名)));
                前端接口_ 前端 = 获取注册的前端(s.目标);
                打印机_ 前端打印 = 前端.创建输出打印机(转换结果);
                打印输出文件((cast(源文件_)(s)), 前端打印, sourceMapGen);
            }
        }
    }
    输出多个文件为一个文件 = &输出多个文件为一个文件·func;
    void 如果需要为多个文件生成一个声明文件·func(源文件_[] 文件组, 转换工厂_!(节点_)[] 声明转换组, 输出结果_ 输出结果) {
        TransformationResult 转换结果;
        转换结果 = transformNodes(resolver, (cast(节点_[])(文件组)), 声明转换组);
        if ((转换结果 !is ··null!(TransformationResult)) && (转换结果.transformed !is ··null!(节点_[])) && 转换结果.transformed.length > 0) {
            foreach (节点_ s; 转换结果.transformed) {
                if (!host.获取前端().是应输出的文件((cast(源文件_)(s)))) {
                    continue;
                }
                dstring mapFileName = 获取基础文件名称(正规化反斜杠((cast(源文件_)(s)).输出文件名));
                SourceMapGenerator sourceMapGen = createSourceMapGenerator(host, mapFileName, ""d, 获取目录路径(正规化路径((cast(源文件_)(s)).输出文件名)));
                前端接口_ 前端 = 获取注册的前端(s.目标);
                打印机_ 前端打印 = 前端.创建输出打印机(转换结果);
                打印输出文件((cast(源文件_)(s)), 前端打印, sourceMapGen);
            }
        }
    }
    如果需要为多个文件生成一个声明文件 = &如果需要为多个文件生成一个声明文件·func;
    void 打印输出文件·func(源文件_ 源文件, 打印机_ printer, SourceMapGenerator sourceMapGenerator) {
        printer.writeFile(源文件, 写出, sourceMapGenerator);
        if (写文件 !is ··null!(写文件回调_)) {
            写文件(源文件.输出文件名, 写出.getText(), false, ··null!(void delegate(dstring)), ··null!(源文件_[]));
            dstring sourceMap = sourceMapGenerator.转为文本();
            写文件(源文件.输出文件名 ~ ".map"d, sourceMap, false, ··null!(void delegate(dstring)), ··null!(源文件_[]));
        }
        写出.clear();
    }
    打印输出文件 = &打印输出文件·func;
    结果 = new 输出结果_(false, 创建数组!(诊断_)());
    host = resolver.获取主机();
    源文件组 = targetSourceFile ? [targetSourceFile] : 过滤!(源文件_)(host.获取源文件组(), (源文件_ s) { return host.获取前端().是应输出的文件(s); });
    if ((源文件组 is ··null!(源文件_[])) || 源文件组.length == 0) {
        return 结果;
    }
    写出 = 创建文本写(sys.新行);
    .forEachEmittedFile!(bool)(host, cast(输出动作类型_!(bool))(输出一组文件), 源文件组, 输出转换组, 结果);
    return 结果;
}
